home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / win / tkWinFont.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  18.3 KB  |  644 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tkWinFont.c --
  3.  *
  4.  *    Contains the Windows implementation of the platform-independant
  5.  *    font package interface.
  6.  *
  7.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  8.  * Copyright (c) 1994 Software Research Associates, Inc. 
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * SCCS: @(#) tkWinFont.c 1.20 97/05/14 15:45:30
  14.  */
  15.  
  16. #include "tkWinInt.h"
  17. #include "tkFont.h"
  18.  
  19. /*
  20.  * The following structure represents Windows' implementation of a font.
  21.  */
  22.  
  23. typedef struct WinFont {
  24.     TkFont font;        /* Stuff used by generic font package.  Must
  25.                  * be first in structure. */
  26.     HFONT hFont;        /* Windows information about font. */
  27.     HWND hwnd;            /* Toplevel window of application that owns
  28.                  * this font, used for getting HDC. */
  29.     int widths[256];        /* Widths of first 256 chars in this font. */
  30. } WinFont;
  31.  
  32. /*
  33.  * The following structure is used as to map between the Tcl strings
  34.  * that represent the system fonts and the numbers used by Windows.
  35.  */
  36.  
  37. static TkStateMap systemMap[] = {
  38.     {ANSI_FIXED_FONT,        "ansifixed"},
  39.     {ANSI_VAR_FONT,        "ansi"},
  40.     {DEVICE_DEFAULT_FONT,   "device"},
  41.     {OEM_FIXED_FONT,        "oemfixed"},
  42.     {SYSTEM_FIXED_FONT,        "systemfixed"},
  43.     {SYSTEM_FONT,        "system"},
  44.     {-1,            NULL}
  45. };
  46.  
  47. #define ABS(x)          (((x) < 0) ? -(x) : (x))
  48.  
  49. static TkFont *        AllocFont _ANSI_ARGS_((TkFont *tkFontPtr, 
  50.                             Tk_Window tkwin, HFONT hFont));
  51. static char *        GetProperty _ANSI_ARGS_((CONST TkFontAttributes *faPtr,
  52.                 CONST char *option));
  53. static int CALLBACK    WinFontFamilyEnumProc _ANSI_ARGS_((ENUMLOGFONT *elfPtr,
  54.                 NEWTEXTMETRIC *ntmPtr, int fontType,
  55.                 LPARAM lParam));
  56.  
  57.  
  58. /*
  59.  *---------------------------------------------------------------------------
  60.  *
  61.  * TkpGetNativeFont --
  62.  *
  63.  *    Map a platform-specific native font name to a TkFont.
  64.  *
  65.  * Results:
  66.  *     The return value is a pointer to a TkFont that represents the
  67.  *    native font.  If a native font by the given name could not be
  68.  *    found, the return value is NULL.  
  69.  *
  70.  *    Every call to this procedure returns a new TkFont structure,
  71.  *    even if the name has already been seen before.  The caller should
  72.  *    call TkpDeleteFont() when the font is no longer needed.
  73.  *
  74.  *    The caller is responsible for initializing the memory associated
  75.  *    with the generic TkFont when this function returns and releasing
  76.  *    the contents of the generic TkFont before calling TkpDeleteFont().
  77.  *
  78.  * Side effects:
  79.  *    None.
  80.  *
  81.  *---------------------------------------------------------------------------
  82.  */
  83.  
  84. TkFont *
  85. TkpGetNativeFont(tkwin, name)
  86.     Tk_Window tkwin;        /* For display where font will be used. */
  87.     CONST char *name;        /* Platform-specific font name. */
  88. {
  89.     int object;
  90.     HFONT hFont;
  91.     
  92.     object = TkFindStateNum(NULL, NULL, systemMap, name);
  93.     if (object < 0) {
  94.     return NULL;
  95.     }
  96.     hFont = GetStockObject(object);
  97.     if (hFont == NULL) {
  98.     panic("TkpGetNativeFont: can't allocate stock font");
  99.     }
  100.  
  101.     return AllocFont(NULL, tkwin, hFont);
  102. }
  103.  
  104. /*
  105.  *---------------------------------------------------------------------------
  106.  *
  107.  * TkpGetFontFromAttributes -- 
  108.  *
  109.  *    Given a desired set of attributes for a font, find a font with
  110.  *    the closest matching attributes.
  111.  *
  112.  * Results:
  113.  *     The return value is a pointer to a TkFont that represents the
  114.  *    font with the desired attributes.  If a font with the desired
  115.  *    attributes could not be constructed, some other font will be
  116.  *    substituted automatically.  NULL is never returned.
  117.  *
  118.  *    Every call to this procedure returns a new TkFont structure,
  119.  *    even if the specified attributes have already been seen before.
  120.  *    The caller should call TkpDeleteFont() to free the platform-
  121.  *    specific data when the font is no longer needed.  
  122.  *
  123.  *    The caller is responsible for initializing the memory associated
  124.  *    with the generic TkFont when this function returns and releasing
  125.  *    the contents of the generic TkFont before calling TkpDeleteFont().
  126.  *
  127.  * Side effects:
  128.  *    None.
  129.  *
  130.  *---------------------------------------------------------------------------
  131.  */
  132. TkFont *
  133. TkpGetFontFromAttributes(tkFontPtr, tkwin, faPtr)
  134.     TkFont *tkFontPtr;        /* If non-NULL, store the information in
  135.                  * this existing TkFont structure, rather than
  136.                  * allocating a new structure to hold the
  137.                  * font; the existing contents of the font
  138.                  * will be released.  If NULL, a new TkFont
  139.                  * structure is allocated. */
  140.     Tk_Window tkwin;        /* For display where font will be used. */
  141.     CONST TkFontAttributes *faPtr;  /* Set of attributes to match. */
  142. {
  143.     LOGFONT lf;
  144.     HFONT hFont;
  145.     Window window;
  146.     HWND hwnd;
  147.     HDC hdc;
  148.  
  149.     window = Tk_WindowId(((TkWindow *) tkwin)->mainPtr->winPtr);
  150.     hwnd = (window == None) ? NULL : TkWinGetHWND(window);
  151.  
  152.     hdc = GetDC(hwnd);
  153.     lf.lfHeight        = -faPtr->pointsize;
  154.     if (lf.lfHeight < 0) {
  155.     lf.lfHeight = MulDiv(lf.lfHeight, 
  156.             254 * WidthOfScreen(Tk_Screen(tkwin)),
  157.         720 * WidthMMOfScreen(Tk_Screen(tkwin)));
  158.     }
  159.     lf.lfWidth        = 0;
  160.     lf.lfEscapement    = 0;
  161.     lf.lfOrientation    = 0;
  162.     lf.lfWeight        = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
  163.     lf.lfItalic        = faPtr->slant;
  164.     lf.lfUnderline    = faPtr->underline;
  165.     lf.lfStrikeOut    = faPtr->overstrike;
  166.     lf.lfCharSet    = DEFAULT_CHARSET;
  167.     lf.lfOutPrecision    = OUT_DEFAULT_PRECIS;
  168.     lf.lfClipPrecision    = CLIP_DEFAULT_PRECIS;
  169.     lf.lfQuality    = DEFAULT_QUALITY;
  170.     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  171.     if (faPtr->family == NULL) {
  172.     lf.lfFaceName[0] = '\0';
  173.     } else {
  174.     lstrcpyn(lf.lfFaceName, faPtr->family, sizeof(lf.lfFaceName));
  175.     }
  176.     ReleaseDC(hwnd, hdc);
  177.  
  178.     /*
  179.      * Replace the standard X and Mac family names with the names that
  180.      * Windows likes.
  181.      */
  182.  
  183.     if ((stricmp(lf.lfFaceName, "Times") == 0)
  184.         || (stricmp(lf.lfFaceName, "New York") == 0)) {
  185.     strcpy(lf.lfFaceName, "Times New Roman");
  186.     } else if ((stricmp(lf.lfFaceName, "Courier") == 0)
  187.         || (stricmp(lf.lfFaceName, "Monaco") == 0)) {
  188.     strcpy(lf.lfFaceName, "Courier New");
  189.     } else if ((stricmp(lf.lfFaceName, "Helvetica") == 0)
  190.         || (stricmp(lf.lfFaceName, "Geneva") == 0)) {
  191.     strcpy(lf.lfFaceName, "Arial");
  192.     }
  193.  
  194.     hFont = CreateFontIndirect(&lf);
  195.     if (hFont == NULL) {
  196.         hFont = GetStockObject(SYSTEM_FONT);
  197.     if (hFont == NULL) {
  198.         panic("TkpGetFontFromAttributes: cannot get system font");
  199.     }
  200.     }
  201.     return AllocFont(tkFontPtr, tkwin, hFont);
  202. }
  203.  
  204. /*
  205.  *---------------------------------------------------------------------------
  206.  *
  207.  * TkpDeleteFont --
  208.  *
  209.  *    Called to release a font allocated by TkpGetNativeFont() or
  210.  *    TkpGetFontFromAttributes().  The caller should have already
  211.  *    released the fields of the TkFont that are used exclusively by
  212.  *    the generic TkFont code.
  213.  *
  214.  * Results:
  215.  *    None.
  216.  *
  217.  * Side effects:
  218.  *    TkFont is deallocated.
  219.  *
  220.  *---------------------------------------------------------------------------
  221.  */
  222.  
  223. void
  224. TkpDeleteFont(tkFontPtr)
  225.     TkFont *tkFontPtr;        /* Token of font to be deleted. */
  226. {
  227.     WinFont *fontPtr;
  228.  
  229.     fontPtr = (WinFont *) tkFontPtr;
  230.     DeleteObject(fontPtr->hFont);
  231.     ckfree((char *) fontPtr);
  232. }
  233.  
  234. /*
  235.  *---------------------------------------------------------------------------
  236.  *
  237.  * TkpGetFontFamilies, WinFontEnumFamilyProc --
  238.  *
  239.  *    Return information about the font families that are available
  240.  *    on the display of the given window.
  241.  *
  242.  * Results:
  243.  *    interp->result is modified to hold a list of all the available
  244.  *    font families.
  245.  *
  246.  * Side effects:
  247.  *    None.
  248.  *
  249.  *---------------------------------------------------------------------------
  250.  */
  251.  
  252. void
  253. TkpGetFontFamilies(interp, tkwin)
  254.     Tcl_Interp *interp;        /* Interp to hold result. */
  255.     Tk_Window tkwin;        /* For display to query. */
  256. {    
  257.     Window window;
  258.     HWND hwnd;
  259.     HDC hdc;
  260.  
  261.     window = Tk_WindowId(tkwin);
  262.     hwnd = (window == (Window) NULL) ? NULL : TkWinGetHWND(window);
  263.  
  264.     hdc = GetDC(hwnd);
  265.     EnumFontFamilies(hdc, NULL, (FONTENUMPROC) WinFontFamilyEnumProc,
  266.         (LPARAM) interp);
  267.     ReleaseDC(hwnd, hdc);
  268. }
  269.  
  270. /* ARGSUSED */
  271.  
  272. static int CALLBACK
  273. WinFontFamilyEnumProc(elfPtr, ntmPtr, fontType, lParam)
  274.     ENUMLOGFONT *elfPtr;    /* Logical-font data. */
  275.     NEWTEXTMETRIC *ntmPtr;    /* Physical-font data (not used). */
  276.     int fontType;        /* Type of font (not used). */
  277.     LPARAM lParam;        /* Interp to hold result. */
  278. {
  279.     Tcl_Interp *interp;
  280.  
  281.     interp = (Tcl_Interp *) lParam;
  282.     Tcl_AppendElement(interp, elfPtr->elfLogFont.lfFaceName);
  283.     return 1;
  284. }
  285.  
  286. /*
  287.  *---------------------------------------------------------------------------
  288.  *
  289.  *  Tk_MeasureChars --
  290.  *
  291.  *    Determine the number of characters from the string that will fit
  292.  *    in the given horizontal span.  The measurement is done under the
  293.  *    assumption that Tk_DrawChars() will be used to actually display
  294.  *    the characters.
  295.  *
  296.  * Results:
  297.  *    The return value is the number of characters from source that
  298.  *    fit into the span that extends from 0 to maxLength.  *lengthPtr is
  299.  *    filled with the x-coordinate of the right edge of the last
  300.  *    character that did fit.
  301.  *
  302.  * Side effects:
  303.  *    None.
  304.  *
  305.  *---------------------------------------------------------------------------
  306.  */
  307. int
  308. Tk_MeasureChars(tkfont, source, numChars, maxLength, flags, lengthPtr)
  309.     Tk_Font tkfont;        /* Font in which characters will be drawn. */
  310.     CONST char *source;        /* Characters to be displayed.  Need not be
  311.                  * '\0' terminated. */
  312.     int numChars;        /* Maximum number of characters to consider
  313.                  * from source string. */
  314.     int maxLength;        /* If > 0, maxLength specifies the longest
  315.                  * permissible line length; don't consider any
  316.                  * character that would cross this
  317.                  * x-position.  If <= 0, then line length is
  318.                  * unbounded and the flags argument is
  319.                  * ignored. */
  320.     int flags;            /* Various flag bits OR-ed together:
  321.                  * TK_PARTIAL_OK means include the last char
  322.                  * which only partially fit on this line.
  323.                  * TK_WHOLE_WORDS means stop on a word
  324.                  * boundary, if possible.
  325.                  * TK_AT_LEAST_ONE means return at least one
  326.                  * character even if no characters fit. */
  327.     int *lengthPtr;        /* Filled with x-location just after the
  328.                  * terminating character. */
  329. {
  330.     WinFont *fontPtr;
  331.     HDC hdc;
  332.     HFONT hFont;
  333.     int curX, curIdx;
  334.  
  335.     /*
  336.      * On the authority of the Gates Empire, Windows does not use kerning
  337.      * or fractional character widths when displaying text on the screen.
  338.      * So that means we can safely measure individual characters or spans
  339.      * of characters and add up the widths w/o any "off-by-one pixel" 
  340.      * errors.  
  341.      */
  342.  
  343.     fontPtr = (WinFont *) tkfont;
  344.  
  345.     hdc = GetDC(fontPtr->hwnd);
  346.     hFont = SelectObject(hdc, fontPtr->hFont);
  347.  
  348.     if (numChars == 0) {
  349.     curX = 0;
  350.     curIdx = 0;
  351.     } else if (maxLength <= 0) {
  352.     SIZE size;
  353.  
  354.     GetTextExtentPoint(hdc, source, numChars, &size);
  355.     curX = size.cx;
  356.     curIdx = numChars;
  357.     } else {
  358.     int newX, termX, sawNonSpace;
  359.     CONST char *term, *end, *p;
  360.     int ch;
  361.  
  362.     ch = UCHAR(*source);
  363.     newX = curX = termX = 0;
  364.     
  365.     term = source;
  366.     end = source + numChars;
  367.  
  368.     sawNonSpace = !isspace(ch);
  369.     for (p = source; ; ) {
  370.         newX += fontPtr->widths[ch];
  371.         if (newX > maxLength) {
  372.         break;
  373.         }
  374.         curX = newX;
  375.         p++;
  376.         if (p >= end) {
  377.         term = end;
  378.         termX = curX;
  379.         break;
  380.         }
  381.  
  382.         ch = UCHAR(*p);
  383.         if (isspace(ch)) {
  384.         if (sawNonSpace) {
  385.             term = p;
  386.             termX = curX;
  387.             sawNonSpace = 0;
  388.         }
  389.         } else {
  390.         sawNonSpace = 1;
  391.         }
  392.     }
  393.  
  394.     /*
  395.      * P points to the first character that doesn't fit in the desired
  396.      * span.  Use the flags to figure out what to return.
  397.      */
  398.  
  399.     if ((flags & TK_PARTIAL_OK) && (p < end) && (curX < maxLength)) {
  400.         /*
  401.          * Include the first character that didn't quite fit in the desired
  402.          * span.  The width returned will include the width of that extra
  403.          * character.
  404.          */
  405.  
  406.         curX = newX;
  407.         p++;
  408.     }
  409.     if ((flags & TK_AT_LEAST_ONE) && (term == source) && (p < end)) {
  410.         term = p;
  411.         termX = curX;
  412.         if (term == source) {
  413.         term++;
  414.         termX = newX;
  415.         }
  416.     } else if ((p >= end) || !(flags & TK_WHOLE_WORDS)) {
  417.         term = p;
  418.         termX = curX;
  419.     }
  420.  
  421.     curX = termX;
  422.     curIdx = term - source;    
  423.     }
  424.  
  425.     SelectObject(hdc, hFont);
  426.     ReleaseDC(fontPtr->hwnd, hdc);
  427.  
  428.     *lengthPtr = curX;
  429.     return curIdx;
  430. }
  431.  
  432. /*
  433.  *---------------------------------------------------------------------------
  434.  *
  435.  * Tk_DrawChars --
  436.  *
  437.  *    Draw a string of characters on the screen.  
  438.  *
  439.  * Results:
  440.  *    None.
  441.  *
  442.  * Side effects:
  443.  *    Information gets drawn on the screen.
  444.  *
  445.  *---------------------------------------------------------------------------
  446.  */
  447.  
  448. void
  449. Tk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y)
  450.     Display *display;        /* Display on which to draw. */
  451.     Drawable drawable;        /* Window or pixmap in which to draw. */
  452.     GC gc;            /* Graphics context for drawing characters. */
  453.     Tk_Font tkfont;        /* Font in which characters will be drawn;
  454.                  * must be the same as font used in GC. */
  455.     CONST char *source;        /* Characters to be displayed.  Need not be
  456.                  * '\0' terminated.  All Tk meta-characters
  457.                  * (tabs, control characters, and newlines)
  458.                  * should be stripped out of the string that
  459.                  * is passed to this function.  If they are
  460.                  * not stripped out, they will be displayed as
  461.                  * regular printing characters. */
  462.     int numChars;        /* Number of characters in string. */
  463.     int x, y;            /* Coordinates at which to place origin of
  464.                  * string when drawing. */
  465. {
  466.     HDC dc;
  467.     HFONT hFont;
  468.     TkWinDCState state;
  469.     WinFont *fontPtr;
  470.  
  471.     fontPtr = (WinFont *) gc->font;
  472.     display->request++;
  473.  
  474.     if (drawable == None) {
  475.     return;
  476.     }
  477.  
  478.     dc = TkWinGetDrawableDC(display, drawable, &state);
  479.  
  480.     SetROP2(dc, tkpWinRopModes[gc->function]);
  481.  
  482.     if ((gc->fill_style == FillStippled
  483.         || gc->fill_style == FillOpaqueStippled)
  484.         && gc->stipple != None) {
  485.     TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
  486.     HBRUSH oldBrush, stipple;
  487.     HBITMAP oldBitmap, bitmap;
  488.     HDC dcMem;
  489.     TEXTMETRIC tm;
  490.     SIZE size;
  491.  
  492.     if (twdPtr->type != TWD_BITMAP) {
  493.         panic("unexpected drawable type in stipple");
  494.     }
  495.  
  496.     /*
  497.      * Select stipple pattern into destination dc.
  498.      */
  499.     
  500.     dcMem = CreateCompatibleDC(dc);
  501.  
  502.     stipple = CreatePatternBrush(twdPtr->bitmap.handle);
  503.     SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
  504.     oldBrush = SelectObject(dc, stipple);
  505.  
  506.     SetTextAlign(dcMem, TA_LEFT | TA_TOP);
  507.     SetTextColor(dcMem, gc->foreground);
  508.     SetBkMode(dcMem, TRANSPARENT);
  509.     SetBkColor(dcMem, RGB(0, 0, 0));
  510.  
  511.         hFont = SelectObject(dcMem, fontPtr->hFont);
  512.  
  513.     /*
  514.      * Compute the bounding box and create a compatible bitmap.
  515.      */
  516.  
  517.     GetTextExtentPoint(dcMem, source, numChars, &size);
  518.     GetTextMetrics(dcMem, &tm);
  519.     size.cx -= tm.tmOverhang;
  520.     bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
  521.     oldBitmap = SelectObject(dcMem, bitmap);
  522.  
  523.     /*
  524.      * The following code is tricky because fonts are rendered in multiple
  525.      * colors.  First we draw onto a black background and copy the white
  526.      * bits.  Then we draw onto a white background and copy the black bits.
  527.      * Both the foreground and background bits of the font are ANDed with
  528.      * the stipple pattern as they are copied.
  529.      */
  530.  
  531.     PatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);
  532.     TextOut(dcMem, 0, 0, source, numChars);
  533.     BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
  534.         0, 0, 0xEA02E9);
  535.     PatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);
  536.     TextOut(dcMem, 0, 0, source, numChars);
  537.     BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
  538.         0, 0, 0x8A0E06);
  539.  
  540.     /*
  541.      * Destroy the temporary bitmap and restore the device context.
  542.      */
  543.  
  544.         SelectObject(dcMem, hFont);
  545.     SelectObject(dcMem, oldBitmap);
  546.     DeleteObject(bitmap);
  547.     DeleteDC(dcMem);
  548.     SelectObject(dc, oldBrush);
  549.     DeleteObject(stipple);
  550.     } else {
  551.     SetTextAlign(dc, TA_LEFT | TA_BASELINE);
  552.     SetTextColor(dc, gc->foreground);
  553.     SetBkMode(dc, TRANSPARENT);
  554.     hFont = SelectObject(dc, fontPtr->hFont);
  555.     TextOut(dc, x, y, source, numChars);
  556.         SelectObject(dc, hFont);
  557.     }
  558.     TkWinReleaseDrawableDC(drawable, dc, &state);
  559. }
  560.  
  561. /*
  562.  *---------------------------------------------------------------------------
  563.  *
  564.  * AllocFont --
  565.  *
  566.  *    Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
  567.  *    Allocates and intializes the memory for a new TkFont that
  568.  *    wraps the platform-specific data.
  569.  *
  570.  * Results:
  571.  *    Returns pointer to newly constructed TkFont.  
  572.  *
  573.  *    The caller is responsible for initializing the fields of the
  574.  *    TkFont that are used exclusively by the generic TkFont code, and
  575.  *    for releasing those fields before calling TkpDeleteFont().
  576.  *
  577.  * Side effects:
  578.  *    Memory allocated.
  579.  *
  580.  *---------------------------------------------------------------------------
  581.  */ 
  582.  
  583. static TkFont *
  584. AllocFont(tkFontPtr, tkwin, hFont)
  585.     TkFont *tkFontPtr;        /* If non-NULL, store the information in
  586.                  * this existing TkFont structure, rather than
  587.                  * allocating a new structure to hold the
  588.                  * font; the existing contents of the font
  589.                  * will be released.  If NULL, a new TkFont
  590.                  * structure is allocated. */
  591.     Tk_Window tkwin;        /* For display where font will be used. */
  592.     HFONT hFont;        /* Windows information about font. */
  593. {
  594.     HWND hwnd;
  595.     WinFont *fontPtr;
  596.     HDC hdc;
  597.     TEXTMETRIC tm;
  598.     Window window;
  599.     char buf[LF_FACESIZE];
  600.     TkFontAttributes *faPtr;
  601.  
  602.     if (tkFontPtr != NULL) {
  603.         fontPtr = (WinFont *) tkFontPtr;
  604.         DeleteObject(fontPtr->hFont);
  605.     } else {
  606.         fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
  607.     }
  608.     
  609.     window = Tk_WindowId(((TkWindow *) tkwin)->mainPtr->winPtr);
  610.     hwnd = (window == None) ? NULL : TkWinGetHWND(window);
  611.  
  612.     hdc = GetDC(hwnd);
  613.     hFont = SelectObject(hdc, hFont);
  614.     GetTextFace(hdc, sizeof(buf), buf);
  615.     GetTextMetrics(hdc, &tm);
  616.     GetCharWidth(hdc, 0, 255, fontPtr->widths);
  617.  
  618.     fontPtr->font.fid    = (Font) fontPtr;
  619.  
  620.     faPtr = &fontPtr->font.fa;
  621.     faPtr->family    = Tk_GetUid(buf);
  622.     faPtr->pointsize    = MulDiv(tm.tmHeight - tm.tmInternalLeading,
  623.         720 * WidthMMOfScreen(Tk_Screen(tkwin)),
  624.         254 * WidthOfScreen(Tk_Screen(tkwin)));
  625.     faPtr->weight    = (tm.tmWeight > FW_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;
  626.     faPtr->slant    = (tm.tmItalic != 0) ? TK_FS_ITALIC : TK_FS_ROMAN;
  627.     faPtr->underline    = (tm.tmUnderlined != 0) ? 1 : 0;
  628.     faPtr->overstrike    = (tm.tmStruckOut != 0) ? 1 : 0;
  629.  
  630.     fontPtr->font.fm.ascent    = tm.tmAscent;
  631.     fontPtr->font.fm.descent    = tm.tmDescent;
  632.     fontPtr->font.fm.maxWidth    = tm.tmMaxCharWidth;
  633.     fontPtr->font.fm.fixed    = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
  634.  
  635.     hFont = SelectObject(hdc, hFont);
  636.     ReleaseDC(hwnd, hdc);
  637.  
  638.     fontPtr->hFont        = hFont;
  639.     fontPtr->hwnd        = hwnd;
  640.  
  641.     return (TkFont *) fontPtr;
  642. }
  643.  
  644.